﻿using System;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
using System.IO;
using UnityEngine.Events;
using Mirror;

public class Ship : NetworkBehaviour
{
    public enum OperationFlag
    {
        NONE = 0,
        MOVE_FORWARD = 1 << 0,
        MOVE_LEFT = 1 << 1,
        MOVE_RIGHT = 1 << 2,
        MOVE_BACK = 1 << 3,
        ROT_LEFT = 1 << 4,
        ROT_RIGHT = 1 << 5,
    };
    #region Public Varible
    public string m_Path;

    [SerializeField, SyncVar(hook = nameof(OnSetShipStruct))]
    public ShipStruct m_ShipStruct = new ShipStruct();
    [SerializeField, SyncVar]
    public int m_FireGroup = -1;
    public GameObject m_ShipInfluenceRelationFlag;

    [NonSerialized]
    public float FightingCapacity = 5;
    [NonSerialized]
    public float m_AddtionalForwardForce = 0;
    [NonSerialized]
    public float m_AddtionalRotationForce = 0;
    [NonSerialized]
    public List<Engine> m_Engines = new List<Engine>();
    [NonSerialized]
    public List<WeaponSlot> m_WeaponSlots = new List<WeaponSlot>();
    [NonSerialized]
    public List<FeatureSlot> m_FeatureSlots = new List<FeatureSlot>();
    [NonSerialized]
    public ShipDestoryCallback OnShipDestory = new ShipDestoryCallback();


    [NonSerialized]
    public float m_DamageMultiply = 1;
    [NonSerialized]
    public float m_ShotRangeMultiply = 1;
    [NonSerialized]
    public float m_ShotVelocityMultiply = 1;
    [NonSerialized]
    public float m_WeaponAngleMultiply = 1;
    [NonSerialized]
    public float VelocityMutiple = 1;
    [NonSerialized]
    public float RotationMutiple = 1;
    [NonSerialized]
    public float SideMoveMutiple = 0.70f;
    [NonSerialized]
    public float BackMoveMutiple = 0.5f;
    [NonSerialized]
    public float ShotVelocityMutiple = 1.0f;
    [NonSerialized]
    public float CollisionDamageMutiple = 1.0f;
    public bool IsShip = true;
    public bool m_AutoFire2 = false;
    public Rigidbody2D m_PullBody;
    public bool m_FireLicense = true;

    [NonSerialized, SyncVar]
    public Vector3 m_Position;
    [NonSerialized, SyncVar]
    public Quaternion m_Rotation = new Quaternion(0, 0, 1, 0);
    [NonSerialized, SyncVar]
    public Vector3 m_Scale = new Vector3(1,1,1);
    [SyncVar]
    public float SkillCoolingTimeCount = 0;
    [SyncVar]
    public bool m_UseSkill = false;
    [SyncVar]
    public bool m_UpdateNetwork = false;
    public float m_SkillCoolingTimeMax = 40;
    public float m_SkillCoolingTimeMaxMultiply = 1;
    #endregion

    #region Public Property
    public float DamageMultiply {
        set {
            foreach (var weaponSlot in m_WeaponSlots)
            {
                m_DamageMultiply = value;
                weaponSlot.DamageMultiply = m_DamageMultiply;
            }
        }
        get { return m_DamageMultiply; }
    }
    public float ShotRangeMultiply
    {
        set
        {
            foreach (var weaponSlot in m_WeaponSlots)
            {
                m_ShotRangeMultiply = value;
                weaponSlot.ShotRangeMultiply = m_ShotRangeMultiply;
            }
        }
        get { return m_ShotRangeMultiply; }
    }
    public float ShotVelocityMultiply
    {
        set
        {
            foreach (var weaponSlot in m_WeaponSlots)
            {
                m_ShotVelocityMultiply = value;
                weaponSlot.ShotVelocityMultiply = m_ShotVelocityMultiply;
            }
        }
        get { return m_ShotVelocityMultiply; }
    }
    public float WeaponAngleMultiply
    {
        set
        {
            foreach (var weaponSlot in m_WeaponSlots)
            {
                m_WeaponAngleMultiply = value;
                weaponSlot.m_WeaponAngleMultiply = m_WeaponAngleMultiply;
            }
        }
        get { return m_WeaponAngleMultiply; }
    }
    public Rigidbody2D PullBody
    {
        set
        {
            m_PullBody = value;
            var joint = GetComponent<DistanceJoint2D>();
            if (joint == null)
                joint = gameObject.AddComponent<DistanceJoint2D>();
            joint.enabled = true;
            joint.connectedBody = m_PullBody;
            joint.enableCollision = true;
            joint.maxDistanceOnly = true;
            m_Hook.gameObject.SetActive(false);
        }
        get { return m_PullBody; }
    }
    public bool UseSkill
    {
        get { return m_UseSkill; }
        set {
            if(m_UseSkill == value)
                return;
            m_UseSkill = value;
            if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
            {
                CmdSetUseSkill(value);
            }
        }
    }
    public float SkillCoolingTimeMax { get { return m_SkillCoolingTimeMax * m_SkillCoolingTimeMaxMultiply; } }
    public bool SkillIsReady { get { return SkillCoolingTimeCount >= SkillCoolingTimeMax; } }

    public bool EnabledShowRange
    {
        set { m_EnabledShowRange = value; }
        get { return m_EnabledShowRange; }
    }
    #endregion

    #region Privete Varible
    LineRenderer m_PullRope;
    [NonSerialized]
    CollsionCallback m_Hook;
    float m_CurrentHookRopeDistance;
    float m_HookRopeDistanceMax = 5;
    Vector3 m_HookTargetPosition;
    int m_HookState = 0;
    float m_RecycleHookTime = 0;
    float m_BeforeStructPoint;//    记录上次的血量，

    float m_EngineFire = 0;
    bool m_IsMoveNow = false;
    string m_StructProcessUIPath = "Perfabs/StructProcess";
    string m_StructEnemyProcessUIPath = "Perfabs/StructEnemyProcess";
    string m_EnergyProcessUIPath = "Perfabs/EnergyProcess";

    string m_PullHookPath = "Perfabs/Ships/FeaturePart/PullHook";
    string m_PullRopePath = "Perfabs/Ships/FeaturePart/PullRope";

    GameObject m_StructValueObj;
    GameObject m_EnergyValueObj;
    float m_Radius = 1;
    public int m_OprationFlag = 0; //    用这个来确定客户端的操作

    int m_isPlayerEnemy = 1;
    private bool m_EnabledShowRange = false;
    #endregion

    public class ShipDestoryCallback : UnityEvent<Ship> { }

    #region UnityCallback
    protected virtual void Awake()
    {

        m_ShipStruct.Electric = m_ShipStruct.m_ElectricMax;
        var bound = GetComponent<SpriteRenderer>().bounds;
        m_Radius = (bound.size.y + bound.size.x) / 4;
        ShipManager.Instance.AddShip(this);
        m_ShipStruct.OnInFluenceChanged = onInfluenceChanged;

        //  初始化抓钩
        m_PullRope = Instantiate(Resources.Load<GameObject>(m_PullRopePath)).GetComponent<LineRenderer>();
        m_PullRope.gameObject.name = "Pullrope:" + gameObject.name;
        m_PullRope.transform.SetParent(gameObject.transform);
        m_PullRope.gameObject.SetActive(false);

        m_Hook = Instantiate(Resources.Load<GameObject>(m_PullHookPath)).GetComponent<CollsionCallback>();
        m_Hook.transform.SetParent(gameObject.transform);
        m_Hook.OnCollision2DEnterCallback = OnHookCollisionEnter;
        m_Hook.gameObject.SetActive(false);

        //  收集引擎和武器组
        SkillCoolingTimeCount = SkillCoolingTimeMax;
        CleanShipComponents();
        collectEngines(gameObject);
        collectSlots(gameObject);
        DamageMultiply = m_DamageMultiply;
        ShotRangeMultiply = m_ShotRangeMultiply;
        ShotVelocityMultiply = m_ShotVelocityMultiply;
        WeaponAngleMultiply = m_WeaponAngleMultiply;
        m_ShipStruct.Influence = m_ShipStruct.Influence;

        //  创建血条和能量条
        if (null == m_StructValueObj)
        {
            if (m_isPlayerEnemy == 1)
                createProcessUI(ref m_StructValueObj, m_StructEnemyProcessUIPath);
            else
                createProcessUI(ref m_StructValueObj, m_StructProcessUIPath);
        }
        if (m_ShipStruct.m_ElectricMax > 0)
            createProcessUI(ref m_EnergyValueObj, m_EnergyProcessUIPath);
        CalcFightingCapacity();

        //  看看有没有预制钩中的东西
        if (m_PullBody != null)
        {
            PullBody = m_PullBody;

        }

        if (m_ShipStruct.m_LicenseLevel == Driver.DriveLevel.LEVEL_D)
        {
            BackMoveMutiple = 0.3f;
        }
    }
    void OnSetShipStruct(ShipStruct _OldshipStruct, ShipStruct _NewshipStruct)
    {
        LoadByStruct(m_ShipStruct);
    }
    protected void Start()
    {
        m_ShipStruct.Electric = m_ShipStruct.m_ElectricMax;
    }

    private void OnDisable()
    {
        if (m_StructValueObj)
            m_StructValueObj.SetActive(false) ;
        if (m_EnergyValueObj)
            m_EnergyValueObj.SetActive(false);
    }
    private void OnEnable()
    {
        if (m_StructValueObj)
            m_StructValueObj.SetActive(true);
        if (m_EnergyValueObj)
            m_EnergyValueObj.SetActive(true);
    }
    // Update is called once per frame
    protected virtual void Update()
    {
        if (m_StructValueObj)
            m_StructValueObj.transform.position = transform.position + new Vector3(-m_Radius, m_Radius, 0);

        if (!IsShip)
            return;
        if (m_EnergyValueObj)
            m_EnergyValueObj.transform.position = transform.position + new Vector3(-m_Radius, m_Radius - m_StructValueObj.transform.localScale.y * 2, 0);

        SkillCoolingTimeCount += Time.deltaTime;
        if(UseSkill)
        {
            PressSkill();
        }
        if(m_FireGroup>=0)
        {
            fireByWeaponGourp(m_FireGroup);
        }

        if (!m_IsMoveNow)
        {
            m_EngineFire -= Time.deltaTime / 2;
            m_EngineFire = Mathf.Max(0, m_EngineFire);
        }
        else
        {
            m_EngineFire += Time.deltaTime / 2;
            m_EngineFire = Mathf.Min(1, m_EngineFire);
        }
        m_IsMoveNow = false;
        for (int i = 0; i < m_Engines.Count; ++i)
        {
            m_Engines[i].FirePower = m_EngineFire;
        }
        UpdateNetwork();
    }
    private void FixedUpdate()
    {
        if (Math.Abs(m_BeforeStructPoint - m_ShipStruct.StructurePoint) > 0.1 && m_StructValueObj && m_StructValueObj.transform.childCount > 0)
        {
            m_BeforeStructPoint = m_ShipStruct.StructurePoint;
            var proccesValue = m_StructValueObj.transform.GetChild(0);
            proccesValue.localScale = new Vector3(m_ShipStruct.StructurePoint / m_ShipStruct.StructurePointMax, 1, 1);
        }
        if (!IsShip)
            return;

        m_ShipStruct.Electric = Mathf.Min(m_ShipStruct.m_ElectricMax, m_ShipStruct.Electric + m_ShipStruct.m_ElectricIncrement * Time.fixedDeltaTime);

        if (m_EnergyValueObj && m_EnergyValueObj.transform.childCount > 0)
        {
            var proccesValue = m_EnergyValueObj.transform.GetChild(0);
            proccesValue.localScale = new Vector3(m_ShipStruct.Electric / m_ShipStruct.m_ElectricMax, 1, 1);
        }

        UpdateHook();
        CheckDirver();
    }
    public void OnCollisionEnter2D(Collision2D collision)
    {
        var ship = collision.collider.gameObject.GetComponent<Ship>();
        var shild = collision.collider.gameObject.GetComponent<ShildFunction>();
        float damage = collision.relativeVelocity.magnitude * 30 * CollisionDamageMutiple;
        SoundsPool.get().PlaySound("Perfabs/Audio/Dong "+ UnityEngine.Random.Range(1, 5), transform.position, 90, damage/ (300 * CollisionDamageMutiple));
        if (ship)
        {
            ship.Boom(damage, Weapon.DamageType.TYPE_KINETIC);
            Boom(damage, Weapon.DamageType.TYPE_KINETIC);
        }
        if (shild)
        {
            shild.Boom(damage, Weapon.DamageType.TYPE_ENERGY);
            Boom(damage/2, Weapon.DamageType.TYPE_ENERGY);
        }
    }

    protected virtual void OnDestroy()
    {
        ShipManager.Instance.RemoveShip(this);
        OnShipDestory.Invoke(this);
        Destroy(m_StructValueObj);
        Destroy(m_EnergyValueObj);

        for(int i=0; i<transform.childCount; ++i)
        {
            Destroy(transform.GetChild(i));
        }

    }
    #endregion

    #region Public Function

    //  基本上给航母和导弹用，用来给小飞机指明我要打谁
    public void ArmShip(Ship ship)
    {
        foreach (var weaponSlot in m_WeaponSlots)
        {
            weaponSlot.ArmShip(ship);
        }
    }

    public void PullHook(Vector3 position)
    {
        if (m_HookState == 0)
        {
            m_HookTargetPosition = position;
            m_HookState = 1;
            m_Hook.transform.localPosition = new Vector3(0, 0, 0);

            m_PullRope.SetPosition(0, transform.position);
            m_PullRope.SetPosition(1, transform.position);
            m_Hook.gameObject.SetActive(true);
            m_PullRope.gameObject.SetActive(true);

        }
        else if (m_HookState == 3)
        {
            RecycleHook();
        }

    }

    public int FindFeatureIndex(Feature feature)
    {
        for(int i=0; i<m_FeatureSlots.Count; ++i)
        {
            if(m_FeatureSlots[i].Feature != null && 
                m_FeatureSlots[i].Feature == feature)
            {
                return i;
            }
        }
        return -1;
    }

    public void OnHookCollisionEnter(Collision2D collision)
    {
        if (UtilsGame.IsOfShips(this, collision.gameObject))
        {
            if (collision.rigidbody != null)
            {
                PullBody = collision.rigidbody;
                m_HookState = 3;
            }
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns> 返回是否发动成功</returns>
    public virtual bool LaunchSkillInClient()
    {
        if (!SkillIsReady)
        {
            MessageShow.Instance.Messaage("技能冷却时间剩余：" + (SkillCoolingTimeMax - SkillCoolingTimeCount).ToString("F2") + " 秒");
            return false;
        }
        CmdUseSkill();
        return true;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <returns> 返回是否发动成功</returns>
    public virtual bool LaunchSkill()
    {
        if (!SkillIsReady)
        {
            MessageShow.Instance.Messaage("技能冷却时间剩余：" + (SkillCoolingTimeMax - SkillCoolingTimeCount).ToString("F2") + " 秒");
            return false;
        }
        SkillCoolingTimeCount = 0;
        return true;
    }
    public virtual bool PressSkill()
    {
        if (!SkillIsReady)
        {
            return false;
        }
        return true;
    }

    public bool m_Switch = false;
    public void SetFeatureSwitch(bool switch2)
    {
        if (m_Switch == switch2)
            return;
        m_Switch = switch2;
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            CmdSetFeatureSwitch(switch2);
            return;
        }
        for (int i = 0; i < m_FeatureSlots.Count; ++i)
        {
            if (m_FeatureSlots[i] &&
                m_FeatureSlots[i].enabled &&
                m_FeatureSlots[i].Feature != null &&
                m_FeatureSlots[i].Feature.m_Type >= Item.ItemsType.FEATURE_SMALL_SHILD &&
                m_FeatureSlots[i].Feature.m_Type <= Item.ItemsType.FEATURE_BIG_SHILD)
            {
                m_FeatureSlots[i].Feature.Switch = m_Switch;
            }
        }
    }
    public void setHighLightEnabled(bool enabled)
    {
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            m_WeaponSlots[i].HighLightObj.SetActive(enabled);
        }
    }


    public void fireAll()
    {
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            var weaponSlot = m_WeaponSlots[i].GetComponent<WeaponSlot>();
            if (weaponSlot)
            {
                weaponSlot.fire();
            }
        }
    }

    public void SetUAVState(UAVFunction.State state, int groupIndex)
    {
        if(UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            CmdSetUAVState(state, groupIndex);
            return;
        }
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            var weaponSlot = m_WeaponSlots[i].GetComponent<WeaponSlot>();
            if (weaponSlot && weaponSlot.WeaponGroup == groupIndex)
            {
                UAV uav = weaponSlot.m_Weapon as UAV;
                if (uav != null)
                    uav.SetUAVState(state);
            }
        }
    }

    public virtual void FireUp(int groupIndex)
    {
    }
    public virtual void fireByWeaponGourp(int groupIndex)
    {
        if (!m_FireLicense)
            return;
        bool isOnline = false;
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            //CmdFireWeaponsByGroup(groupIndex);
            isOnline = true;
        }
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            var weaponSlot = m_WeaponSlots[i].GetComponent<WeaponSlot>();
            if (weaponSlot && weaponSlot.WeaponGroup == groupIndex)
            {
                if (isOnline)
                    weaponSlot.FireOnlyEffect();
                else
                    weaponSlot.fire();
            }
        }
    }
    public void fireFeatureAll()
    {
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            CmdFireFeature();
            return;
        }

        for (int i = 0; i < m_FeatureSlots.Count; ++i)
        {
            var featureSlot = m_FeatureSlots[i].GetComponent<FeatureSlot>();
            if (featureSlot)
            {
                featureSlot.fire();
            }
        }
    }

    /// <summary>
    ///     让武器瞄准该点
    /// </summary>
    /// <param name="position"></param>
    public void arm(Vector3 position, int group)
    {
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            m_WeaponSlots[i].m_IsUse = false;
            if (group == m_WeaponSlots[i].WeaponGroup ||
                m_WeaponSlots[i].m_FireMode == WeaponSlot.FireMode.WEAPON_MODE_MANUAL)
            {
                m_WeaponSlots[i].arm(position);
                m_WeaponSlots[i].m_IsUse = true;
            }
        }
    }

    /// <summary>
    /// 派遣武器高优先级歼灭的目标
    /// </summary>
    /// <param name="targets"></param>
    public void SmashTarget(List<ArmTarget> targets, bool isHigh = true)
    {
        foreach (var target in targets)
        {
            foreach (var weaponSlot in m_WeaponSlots)
            {
                //   如果存在高优先级，或者在射程外则不派遣该武器
                if (weaponSlot.TargetHighPriority != null ||
                    null == weaponSlot.m_Weapon ||
                    !target.Target ||
                    weaponSlot.m_Weapon.ShutRange + (weaponSlot.m_Weapon.ShutRange * 0.5) < target.Distance)
                    continue;
                var uavf = target.Target.GetComponent<UAVFunction>();
                if (uavf && weaponSlot.m_Weapon.m_Speciality == Weapon.Speciality.RUIN)
                    continue;

                //  如果武器不是点防御，则低优先级打无人机
                if (uavf && weaponSlot.m_Weapon.m_Speciality != Weapon.Speciality.POINT_DEFENSE)
                    isHigh = false;

                var uav = weaponSlot.m_Weapon as UAV;
                if (uav != null ||
                    weaponSlot.CheckInAngle(target.Target.transform.position))
                {
                    if (isHigh)
                        weaponSlot.TargetHighPriority = target.Target;
                    else
                        weaponSlot.Target = target.Target;
                }
            }
        }
    }

    /// <summary>
    ///     让舰船看向某个方向
    /// </summary>
    /// <param name="position"></param>
    public void Focus(Vector3 position)
    {
        var targetDifference = position - transform.position;
        var targetDir = targetDifference.normalized;
        float z = Vector3.Cross(targetDir, transform.up).z;
        float angle = Mathf.Abs(Vector3.Angle(targetDir, transform.up));
        
        if (z <= 0)
            rotationLeft(Mathf.Clamp(angle / 180f + 0.5f, 0, 1));
        else
            rotationRight(Mathf.Clamp(angle / 180f + 0.5f, 0, 1));
    }

    /// <summary>
    ///     当击中该舰船请调用这个函数产生伤害
    /// </summary>
    /// <param name="damage"></param>
    /// <param name="type"></param>
    public bool Boom(float damage, Weapon.DamageType type)
    {
        switch (type)
        {
            case Weapon.DamageType.TYPE_EXPLOSION:
                damage *= 2;
                break;
            case Weapon.DamageType.TYPE_KINETIC:
                damage /= 2;
                break;
        }
        m_ShipStruct.StructurePoint -= damage;

        if (UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
            RpcSyncStruct(m_ShipStruct.StructurePoint);

        if (m_ShipStruct.StructurePoint <= 0)
        {
            if (UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
                RpcBoomEffect();

            BoomEffect();
            Destroy(gameObject);
            return true;
        }
        return false;
    }
    public void BoomEffect()
    {
        GameObject obj = Resources.Load<GameObject>("Perfabs/Effect/Boom");
        GameObject boomObj = Instantiate(obj);
        boomObj.transform.position = gameObject.transform.position;
        if (boomObj.GetComponent<ParticleSystem>())
            boomObj.GetComponent<ParticleSystem>().Play();
        Destroy(boomObj, 5);
    }

    /// <summary>
    ///     显示武器组的攻击范围
    /// </summary>
    /// <param name="weaponGroup"></param>
    public void SetShowRange(int weaponGroup)
    {
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            if (m_WeaponSlots[i].WeaponGroup == weaponGroup &&
                m_EnabledShowRange)
            {
                m_WeaponSlots[i].ShowRange = true;
            }
            else
            {
                m_WeaponSlots[i].ShowRange = false;
            }
        }
    }
    virtual public void moveForward()
    {
        //if(UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        //{
        //    m_OprationFlag |= (int)OperationFlag.MOVE_FORWARD;
        //    return;
        //}
        var body = GetComponent<Rigidbody2D>();
        body.AddForce(transform.up * (m_ShipStruct.VelocityMax * VelocityMutiple * Time.deltaTime));
        m_IsMoveNow = true;
    }

    virtual public void moveLeft()
    {
        //if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        //{
        //    m_OprationFlag = (m_OprationFlag | (int)OperationFlag.MOVE_LEFT);
        //    return;
        //}
        var body = GetComponent<Rigidbody2D>();
        body.AddForce(-transform.right * ((m_ShipStruct.VelocityMax * VelocityMutiple * SideMoveMutiple) * Time.deltaTime));
        m_IsMoveNow = true;
    }
    virtual public void moveRight()
    {
        //if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        //{
        //    m_OprationFlag |= (int)OperationFlag.MOVE_RIGHT;
        //    return;
        //}
        var body = GetComponent<Rigidbody2D>();
        body.AddForce(transform.right * ((m_ShipStruct.VelocityMax * VelocityMutiple * SideMoveMutiple) * Time.deltaTime));
        m_IsMoveNow = true;
    }

    virtual public void moveBack()
    {
        //if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        //{
        //    m_OprationFlag |= (int)OperationFlag.MOVE_BACK;
        //    return;
        //}
        var body = GetComponent<Rigidbody2D>();
        body.AddForce(-transform.up * ((m_ShipStruct.VelocityMax * VelocityMutiple * BackMoveMutiple) * Time.deltaTime));
        m_IsMoveNow = true;
    }
    virtual public void AddForce(Vector3 dir, float force)
    {
        var body = GetComponent<Rigidbody2D>();
        body.AddForce(dir * force);
        if(UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
        {
            RpcAddForce(dir, force);
        }
    }
    virtual public void AddTorque(float torque)
    {
        var body = GetComponent<Rigidbody2D>();
        body.AddTorque(torque);
        if (UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
        {
            RpcAddTorque(torque);
        }
    }
    virtual public void rotationLeft(float power = 1)
    {
        //if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        //{
        //    m_OprationFlag |= (int)OperationFlag.ROT_LEFT;  
        //    return;
        //}
        var body = GetComponent<Rigidbody2D>();
        body.AddTorque(m_ShipStruct.RotateSpeedMax * RotationMutiple * Time.deltaTime * power);
    }

    virtual public void rotationRight(float power = 1)
    {
        //if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        //{
        //    m_OprationFlag |= (int)OperationFlag.ROT_RIGHT;
        //    return;
        //}
        var body = GetComponent<Rigidbody2D>();
        body.AddTorque(-m_ShipStruct.RotateSpeedMax * RotationMutiple * Time.deltaTime * power);
    }
    /// <summary>
    ///     设置所有武器的开火模式
    /// </summary>
    /// <param name="fireMode"></param>
    public void setAllWeaponSlotFireMode(WeaponSlot.FireMode fireMode)
    {
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            m_WeaponSlots[i].FireMode2 = fireMode;
        }
    }

    public virtual JsonData save()
    {
        JsonData root = new JsonData();
        root["ShipPath"] = m_Path;
        root["WeaponSlots"] = new JsonData();
        root["WeaponSlots"].SetJsonType(JsonType.Array);
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            if (m_WeaponSlots[i].m_Weapon != null)
            {
                JsonData jsonWeapon = new JsonData();
                jsonWeapon.SetJsonType(JsonType.Object);
                jsonWeapon["WeaponReference"] = Item.getItemEnumString(m_WeaponSlots[i].m_Weapon.m_Type);
                jsonWeapon["Group"] = m_WeaponSlots[i].WeaponGroup;
                jsonWeapon["AutoFire"] = (m_WeaponSlots[i].FireMode2 == WeaponSlot.FireMode.WEAPON_MODE_AUTO);
                jsonWeapon["Index"] = i;
                root["WeaponSlots"].Add(jsonWeapon);
            }
        }
        return root;
    }
    public virtual ShipNetworkMessage SaveToNetworkMessage()
    {
        ShipNetworkMessage message = new ShipNetworkMessage(null, "");
        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            if (message.m_ShipStruct.m_Weapons.Count <= i)
                message.m_ShipStruct.m_Weapons.Add(new WeaponSlotStruct());

            if (m_WeaponSlots[i].m_Weapon != null)
                message.m_ShipStruct.m_Weapons[i].m_TypeS = m_WeaponSlots[i].m_Weapon.m_Type.ToString();
            message.m_ShipStruct.m_Weapons[i].m_GroupIndex = m_WeaponSlots[i].WeaponGroup;
            message.m_ShipStruct.m_Weapons[i].m_IsAutoFire = (m_WeaponSlots[i].m_FireMode == WeaponSlot.FireMode.WEAPON_MODE_AUTO);

        }
        for (int i = 0; i < m_FeatureSlots.Count; ++i)
        {
            if (message.m_ShipStruct.m_Features.Count <= i)
                message.m_ShipStruct.m_Features.Add(new FeatureSlotStruct());

            if (m_FeatureSlots[i].Feature != null)
                message.m_ShipStruct.m_Features[i].m_TypeS = m_FeatureSlots[i].Feature.m_Type.ToString();

        }
        message.m_ShipPath = m_Path;
        message.m_ShipStruct = m_ShipStruct;
        return message;
    }

    public static Ship LoadByNetworkMessage(ShipNetworkMessage message)
    {
        var obj = Resources.Load<GameObject>(message.m_ShipPath);
        if (obj)
        {
            GameObject gobj = Instantiate(obj);
            Ship ship = gobj.GetComponent<Ship>();
            message.m_ShipStruct.LoadStruct = true;
            ship.m_ShipStruct = message.m_ShipStruct;
            return ship;
        }
        return null;
    }

    public void LoadByStruct(ShipStruct shipStruct)
    {
        m_ShipStruct = shipStruct;
        for (int i = 0; i < m_ShipStruct.m_Weapons.Count; ++i)
        {
            m_WeaponSlots[i].switchWeapon(ItemFactory.Instance.createItem(m_ShipStruct.m_Weapons[i].m_TypeS) as Weapon);
            m_WeaponSlots[i].WeaponGroup = m_ShipStruct.m_Weapons[i].m_GroupIndex;
            m_WeaponSlots[i].m_FireMode = m_ShipStruct.m_Weapons[i].m_IsAutoFire ? WeaponSlot.FireMode.WEAPON_MODE_AUTO : WeaponSlot.FireMode.WEAPON_MODE_MANUAL;
        }
        for (int i = 0; i < m_ShipStruct.m_Features.Count; ++i)
        {
            m_FeatureSlots[i].switchFeature(ItemFactory.Instance.createItem(m_ShipStruct.m_Features[i].m_TypeS) as Feature);
        }
    }

    public static Ship loadByJson(JsonData json)
    {
        try
        {

            string shipPath = json["ShipPath"].ValueAsString();
            var obj = Resources.Load<GameObject>(shipPath);
            if (obj)
            {
                GameObject gobj = Instantiate(obj);
                Ship ship = gobj.GetComponent<Ship>();
                ship.load(json);
                return ship;
            }
        }
        catch
        {
            Debug.Log("ship load faild, config error. : ");
        }
        return null;
    }

    public static Ship loadByFile(string fileName)
    {
        string data;
        using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
        {
            FileInfo info = new System.IO.FileInfo(fileName);
            byte[] array = new byte[info.Length];
            fs.Read(array, 0, (int)info.Length);
            fs.Close();
            data = System.Text.Encoding.Default.GetString(array);
        }
        return load(data);
    }

    public static Ship load(string data)
    {
        if (data.Length == 0)
            return null;
        JsonData jsonData = JsonMapper.ToObject(data);
        return loadByJson(jsonData);
    }

    public virtual bool load(JsonData json)
    {
        CleanShipComponents();
        collectEngines(gameObject);
        collectSlots(gameObject);
        for (int i = 0, j = 0; i < m_WeaponSlots.Count && j < json["WeaponSlots"].Count; ++i, ++j)
        {
            var jsonSlot = json["WeaponSlots"][j];
            int index = jsonSlot["Index"].ValueAsInt();
            if (index < m_WeaponSlots.Count)
            {
                var weaponType = jsonSlot["WeaponReference"].ValueAsString();
                m_WeaponSlots[index].switchWeapon(ItemFactory.Instance.createItem(weaponType) as Weapon);
                m_WeaponSlots[index].WeaponGroup = jsonSlot["Group"].ValueAsInt();
                m_WeaponSlots[index].FireMode2 = (jsonSlot["AutoFire"].ValueAsBoolean() ? WeaponSlot.FireMode.WEAPON_MODE_AUTO : WeaponSlot.FireMode.WEAPON_MODE_MANUAL);

                m_ShipStruct.m_Weapons[index].m_TypeS = weaponType;
                m_ShipStruct.m_Weapons[index].m_GroupIndex = m_WeaponSlots[index].WeaponGroup;
                m_ShipStruct.m_Weapons[index].m_IsAutoFire = (m_WeaponSlots[index].FireMode2 == WeaponSlot.FireMode.WEAPON_MODE_AUTO);
            }
        }
        return true;
    }
    public virtual void UpdateTransfomrOnline()
    {
        if (UtilsGame.IsOnline() && !UtilsGame.IsServer(gameObject))
        {
            if (isLocalPlayer)
                transform.position = transform.position;
        }
    }
    public virtual void OnChase()
    {
    }
    public virtual void OnFight()
    {
    }
    public virtual void OnRetreat()
    {
    }
    #endregion

    #region Privete Function 

    float m_NetworkUpdateTimeCount = 0;
    float m_NetworkUpdateTimeCountMax = 0.1f;
    void UpdateNetwork()
    {
        if (!UtilsGame.IsOnline() || !m_UpdateNetwork)
            return;
        /////////////////////////////////  每帧执行 ////////////////////////////////////////
        //if(!isLocalPlayer)
        //{
        //}
        float lerpValue = Mathf.Clamp(Time.deltaTime * 10.0f, 0.0f, 1.0f);
        //Debug.Log("lerpValue:"+lerpValue);
        if(!isLocalPlayer)
        {
            transform.position = Vector3.Lerp(transform.position, m_Position, lerpValue);
            transform.rotation = Quaternion.Lerp(transform.rotation, m_Rotation, lerpValue);
            //transform.localScale = Vector3.Lerp(transform.localScale, m_Scale, lerpValue);
        }

        //if (UtilsGame.IsServer(gameObject))
        //{
        //    //  服务器要根据客户端发过来的基本操作指令移动或旋转飞机
        //    if ((m_OprationFlag & (int)OperationFlag.MOVE_FORWARD) == (int)OperationFlag.MOVE_FORWARD)
        //        moveForward();
        //    if ((m_OprationFlag & (int)OperationFlag.MOVE_LEFT) == (int)OperationFlag.MOVE_LEFT)
        //        moveLeft();
        //    if ((m_OprationFlag & (int)OperationFlag.MOVE_RIGHT) == (int)OperationFlag.MOVE_RIGHT)
        //        moveRight();
        //    if ((m_OprationFlag & (int)OperationFlag.MOVE_BACK) == (int)OperationFlag.MOVE_BACK)
        //        moveBack();
        //    if ((m_OprationFlag & (int)OperationFlag.ROT_LEFT) == (int)OperationFlag.ROT_LEFT)
        //        rotationLeft(1);
        //    if ((m_OprationFlag & (int)OperationFlag.ROT_RIGHT) == (int)OperationFlag.ROT_RIGHT)
        //        rotationRight(1);
        //}


        ////////////////////////////////// 固定时间执行 ///////////////////////////////////////////////////////
        m_NetworkUpdateTimeCount += Time.deltaTime;
        if (m_NetworkUpdateTimeCount < m_NetworkUpdateTimeCountMax)
            return;
        m_NetworkUpdateTimeCount = 0;
        if (!UtilsGame.IsServer(gameObject))
        {
            if(NetworkClient.ready && isLocalPlayer)
            {
                //CmdSendOprationFlag(m_OprationFlag);
                CmdSyncTransform(transform.position, transform.rotation, transform.localScale);
            }
            //m_OprationFlag = (int)OperationFlag.NONE;
            return;
        }
        RpcSyncTransform(transform.position, transform.rotation, transform.localScale);

        List<WeaponSlotStruct> weaponSlotsStruct = m_ShipStruct.m_Weapons;
        for (int i=0; i<m_WeaponSlots.Count && i < weaponSlotsStruct.Count; ++i)
        {
            weaponSlotsStruct[i].m_Angle = m_WeaponSlots[i].m_Angle;
            weaponSlotsStruct[i].m_CoolingTime = m_WeaponSlots[i].ShutCooling;
            weaponSlotsStruct[i].m_HasFireLicense = m_WeaponSlots[i].m_FireLicense;
            weaponSlotsStruct[i].m_Firing = m_WeaponSlots[i].m_Firing;

            if(m_WeaponSlots[i].m_Weapon != null)
            {
                weaponSlotsStruct[i].m_ErrorValue = m_WeaponSlots[i].m_Weapon.m_ShotErrorValue;
            }
        }
        List<FeatureSlotStruct> featureSlotsStruct = m_ShipStruct.m_Features;
        for (int i = 0; i < m_FeatureSlots.Count && i < featureSlotsStruct.Count; ++i)
        {
            if (m_FeatureSlots[i].Feature == null)
                continue;
            switch (m_FeatureSlots[i].Feature.m_Type)
            {
                case Item.ItemsType.FEATURE_SMALL_SHILD:
                case Item.ItemsType.FEATURE_MIDDLE_SHILD:
                case Item.ItemsType.FEATURE_BIG_SHILD:
                    var shild = m_FeatureSlots[i].Feature as Shild;
                    featureSlotsStruct[i].m_Value = shild.Energy;
                    featureSlotsStruct[i].m_Switch = shild.m_Switch;
                    break;
            }
        }
        RpcSyncElectric(m_ShipStruct.Electric);
        RpcWeaponsStateChanged(weaponSlotsStruct);
        RpcFeaturesStateChanged(featureSlotsStruct);

    }
    void CheckDirver()
    {
        var driver = GetComponent<Driver>();
        if (driver == null || driver.enabled == false)
        {
            var rigibody = GetComponent<Rigidbody2D>();
            if (rigibody)
                rigibody.drag = 0.1f;
        }
        else
        {
            var rigibody = GetComponent<Rigidbody2D>();
            if (rigibody)
                rigibody.drag = 0.7f;
        }
    }

    void UpdateHook()
    {
        //  更新钩子
        if (m_HookState == 1)
        {
            m_HookTargetPosition.z = 0;
            var relativeDeffence = transform.position - m_HookTargetPosition;
            var relativeHookDeffence = m_Hook.transform.position - transform.position;
            var relativeDir = -relativeDeffence.normalized;
            m_Hook.transform.position = m_Hook.transform.position + relativeDir * Time.fixedDeltaTime * 7;
            m_Hook.transform.rotation = Quaternion.FromToRotation(Vector3.up, relativeDir);
            m_RecycleHookTime = 0;
            if (relativeHookDeffence.magnitude > m_HookRopeDistanceMax)
            {
                m_HookState = 2;
                m_HookTargetPosition = m_Hook.transform.position;
            }
        }
        else if (m_HookState == 2)
        {
            m_RecycleHookTime += Time.fixedDeltaTime;
            if (m_RecycleHookTime >= 0.3f)
            {
                m_PullRope.gameObject.SetActive(false);
                m_Hook.gameObject.SetActive(false);
                m_HookState = 0;
            }
            var resultVec3 = Vector3.Lerp(m_HookTargetPosition, transform.position, m_RecycleHookTime / 0.3f);
            m_Hook.transform.position = resultVec3;
        }


        if (m_PullRope != null)
        {
            Vector3 endPos = m_Hook.transform.position;
            if (m_PullBody != null)
                endPos = m_PullBody.transform.position;
            m_PullRope.SetPosition(0, transform.position);
            m_PullRope.SetPosition(1, endPos);
            m_Hook.transform.position = endPos;

            //  修船
            if (m_PullBody != null)
            {
                var shipStation = m_PullBody.GetComponent<ShipStation>();
                if (shipStation)
                {
                    float translateElectric = shipStation.m_ShipStruct.m_ElectricPower * Time.deltaTime;
                    if (shipStation.m_ShipStruct.Electric > translateElectric &&
                        m_ShipStruct.m_ElectricMax - m_ShipStruct.Electric > translateElectric)
                    {
                        shipStation.m_ShipStruct.Electric -= translateElectric;
                        m_ShipStruct.Electric += translateElectric;
                    }

                    float translateStruct = shipStation.m_MaintineSpeed * Time.deltaTime;
                    if (shipStation.m_PerfabStructPoint > 0)
                        shipStation.m_PerfabStructPoint -= translateStruct;
                    else if (shipStation.m_ShipStruct.StructurePoint > translateStruct)
                        shipStation.m_ShipStruct.StructurePoint -= translateStruct;
                    else
                        translateStruct = 0;
                    m_ShipStruct.StructurePoint += translateStruct;
                }
            }
        }
        if (m_PullBody == null && m_HookState == 3)
        {
            RecycleHook();
        }
    }

    void RecycleHook()
    {
        m_RecycleHookTime = 0;
        m_PullBody = null;
        var joint = GetComponent<DistanceJoint2D>();
        if (joint != null)
            joint.enabled = false;
        m_HookTargetPosition = m_Hook.transform.position;
        m_HookState = 2;
    }

    void createProcessUI(ref GameObject objs, string path)
    {
        if(objs)
            Destroy(objs);

        var obj = Resources.Load<GameObject>(path);
        var uiParent = GameObject.Find("Process");
        if (obj)
        {
            GameObject proceesValue = Instantiate(obj as GameObject);

            var newScale = proceesValue.transform.localScale;
            newScale.x = m_Radius * 2;

            proceesValue.transform.localPosition = new Vector3(-m_Radius, m_Radius, 0);
            proceesValue.transform.localScale = newScale;
            objs = proceesValue.gameObject;
            if (uiParent)
                objs.transform.SetParent(uiParent.transform);
        }
    }


    /// <summary>
    ///     检查舰船上的引擎，并登记
    /// </summary>
    /// <param name="obj"></param>
    protected void collectEngines(GameObject obj)
    {
        Engine engine = obj.GetComponent<Engine>();
        if (engine != null)
        {
            m_Engines.Add(engine);
        }

        for (int i = 0; i < obj.transform.childCount; ++i)
        {
            collectEngines(obj.transform.GetChild(i).gameObject);
        }
    }

    /// <summary>
    ///     检查坚船上的槽，并登记
    /// </summary>
    /// <param name="obj"></param>
    protected void collectSlots(GameObject obj)
    {
        WeaponSlot weaponSlot = obj.GetComponent<WeaponSlot>();
        FeatureSlot featureSlot = obj.GetComponent<FeatureSlot>();

        if (weaponSlot != null)
        {
            weaponSlot.m_Ship = this;
            m_WeaponSlots.Add(weaponSlot);
            m_ShipStruct.m_Weapons.Add(new WeaponSlotStruct());
        }

        if (featureSlot != null)
        {
            featureSlot.m_Ship = this;
            m_FeatureSlots.Add(featureSlot);
            m_ShipStruct.m_Features.Add(new FeatureSlotStruct());
        }

        for (int i = 0; i < obj.transform.childCount; ++i)
        {
            collectSlots(obj.transform.GetChild(i).gameObject);
        }
    }


    /// <summary>
    ///     当势力发生变化的时候
    /// </summary>
    /// <param name="newInfluenceName"></param>
    void onInfluenceChanged(string newInfluenceName)
    {
        m_isPlayerEnemy = -1;
        var influence = InfluenceMG.get().find(newInfluenceName);
        if (influence == null)
        {
            //Debug.LogWarning("unknow infouence :"+ newInfluenceName);
            return;
        }
        if (influence.Name != InfluenceMG.INFLUENCE_PLAYER && m_ShipInfluenceRelationFlag)
        {
            if (influence.findHostile(InfluenceMG.INFLUENCE_PLAYER) >= 0)
            {
                SpriteRenderer sprite = m_ShipInfluenceRelationFlag.GetComponent<SpriteRenderer>();
                sprite.material = Resources.Load<Material>("Materials/Colors/Enemy");
                m_isPlayerEnemy = 1;
            }
            else
            {
                SpriteRenderer sprite = m_ShipInfluenceRelationFlag.GetComponent<SpriteRenderer>();
                sprite.material = Resources.Load<Material>("Materials/Colors/Friend");
                m_isPlayerEnemy = 0;
            }

            for (int i = 0; i < m_WeaponSlots.Count; ++i)
            {
                m_WeaponSlots[i].FireMode2 = WeaponSlot.FireMode.WEAPON_MODE_AUTO;
            }
        }
        if (m_isPlayerEnemy == 1)
            createProcessUI(ref m_StructValueObj, m_StructEnemyProcessUIPath);
        else
            createProcessUI(ref m_StructValueObj, m_StructProcessUIPath);
    }

    void CalcFightingCapacity()
    {


        for (int i = 0; i < m_WeaponSlots.Count; ++i)
        {
            float weaponFightingCapacity = 5;
            switch (m_WeaponSlots[i].m_Level)
            {
                case Weapon.Level.LEVEL_SMALL:
                    weaponFightingCapacity = 3;
                    break;
                case Weapon.Level.LEVEL_MIDDLE:
                    weaponFightingCapacity = 5;
                    break;
                case Weapon.Level.LEVEL_BIG:
                    weaponFightingCapacity = 8;
                    break;
            }
            FightingCapacity += weaponFightingCapacity;
        }

        for (int i = 0; i < m_FeatureSlots.Count; ++i)
        {
            float weaponFightingCapacity = 5;
            FightingCapacity += weaponFightingCapacity;
        }

        FightingCapacity += m_ShipStruct.StructurePointMax / 80;
        FightingCapacity += m_ShipStruct.VelocityMax / 12.0f;
        FightingCapacity += m_ShipStruct.RotateSpeedMax / 10.0f;
        FightingCapacity += m_ShipStruct.m_ElectricMax / 30.0f;
        FightingCapacity += m_ShipStruct.m_ElectricPower / 10.0f;
    }

    void CleanShipComponents()
    {
        m_Engines.Clear();
        m_WeaponSlots.Clear();
        m_FeatureSlots.Clear();
        m_ShipStruct.m_Weapons.Clear();
        m_ShipStruct.m_Features.Clear();
    }

    #endregion

    #region Command
    [Command]
    public void CmdSetFireGroup(int group)
    {
        m_FireGroup = group;
    }
    [Command]
    public void CmdLoadShipByStruct(ShipStruct structs)
    {
        LoadByStruct(structs);
    }
    [Command]
    public void CmdSetFeatureSwitch(bool switch2)
    {
        SetFeatureSwitch(switch2);
    }

    [Command]
    void CmdFireWeaponsByGroup(int groupIndex)
    {
        fireByWeaponGourp(groupIndex);
    }

    [Command]
    void CmdFireFeature()
    {
        fireFeatureAll();
    }
    [Command]
    public void CmdUseSkill()
    {
        RpcUseSkill();
    }
    [Command]
    public void CmdSetUAVState(UAVFunction.State state, int groupIndex)
    {
        SetUAVState(state, groupIndex);
    }
    [Command]
    public void CmdSetUseSkill(bool value)
    {
        m_UseSkill = value;
    }
    [Command]
    public void CmdSendOprationFlag(int value)
    {
        m_OprationFlag = value;
    }
    [Command]
    public void CmdSyncTransform(Vector3 position, Quaternion rotation, Vector3 scale)
    {
        m_Position = position;
        m_Rotation = rotation;
        m_Scale = scale;
    }
    #endregion
    #region ClientRpc

    [ClientRpc]
    public void RpcAddForce(Vector3 direction, float power)
    {
        if(UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
        {
            return;
        }
        AddForce(direction, power);
    }
    [ClientRpc]
    public void RpcAddTorque(float torque)
    {
        if(UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
        {
            return;
        }
        AddTorque(torque);
    }
    [ClientRpc]
    public void RpcSyncTransform(Vector3 position, Quaternion rotation, Vector3 scale)
    {
        m_Position = position;
        m_Rotation = rotation;
        m_Scale = scale;
    }

    [ClientRpc]
    void RpcSyncStruct(float structValue)
    {
        m_ShipStruct.StructurePoint = structValue;
    }
    [ClientRpc]
    void RpcSyncElectric(float electric)
    {
        m_ShipStruct.Electric = electric;
    }
    [ClientRpc]
    void RpcUseSkill()
    {
        LaunchSkill();
        UpdateNetwork();
    }
    [ClientRpc]
    void RpcBoomEffect()
    {
        BoomEffect();
    }
    [ClientRpc]
    public void RpcOnShildExplosion(int index)
    {
        if (index < m_FeatureSlots.Count && 
            m_FeatureSlots[index].Feature != null &&
            m_FeatureSlots[index].Feature as Shild != null)
        {
            var shild = (m_FeatureSlots[index].Feature as Shild);
            shild.Explosion();
        }
    }
    [ClientRpc]
    void RpcWeaponsStateChanged(List<WeaponSlotStruct> structS)
    {
        if (UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
            return;

        for (int i = 0; i < m_WeaponSlots.Count && i < structS.Count; ++i)
        {
            m_WeaponSlots[i].m_TargetAngle = structS[i].m_Angle;
            if (Mathf.Abs(structS[i].m_CoolingTime - m_WeaponSlots[i].ShutCooling) > 0.5f)
                m_WeaponSlots[i].ShutCooling = structS[i].m_CoolingTime;
            m_WeaponSlots[i].m_FireLicense = structS[i].m_HasFireLicense;
            m_WeaponSlots[i].m_Firing = structS[i].m_Firing;
            if (m_WeaponSlots[i].m_Weapon != null)
                m_WeaponSlots[i].m_Weapon.m_ShotErrorValue = structS[i].m_ErrorValue;
        }
    }
    [ClientRpc]
    void RpcFeaturesStateChanged(List<FeatureSlotStruct> structS)
    {
        if (UtilsGame.IsOnline() && UtilsGame.IsServer(gameObject))
            return;
        for (int i = 0; i < m_FeatureSlots.Count && i < structS.Count; ++i)
        {
            if (m_FeatureSlots[i].Feature == null)
                continue;
            switch (m_FeatureSlots[i].Feature.m_Type)
            {
                case Item.ItemsType.FEATURE_SMALL_SHILD:
                case Item.ItemsType.FEATURE_MIDDLE_SHILD:
                case Item.ItemsType.FEATURE_BIG_SHILD:
                    var shild = m_FeatureSlots[i].Feature as Shild;
                    shild.Energy = structS[i].m_Value;
                    shild.m_Switch = structS[i].m_Switch;
                    break;
            }
        }
    }
    #endregion

}
